/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.spring.sample.graphql.greeting;

import com.sun.istack.NotNull;
import graphql.GraphQLContext;
import graphql.schema.DataFetchingEnvironment;
import lombok.Value;
import org.springframework.data.web.ProjectedPayload;
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.Arguments;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST;


@Controller
public class GreetingController {

	@QueryMapping
	public String greeting() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		return "Hello " + attributes.getAttribute(RequestAttributeFilter.NAME_ATTRIBUTE, SCOPE_REQUEST);
	}
	/**直接 @Arguments MyInputProjection in 把所有的参数全部都放进去MyInputProjection类型中去。
	 * 就缺点是啰嗦啊。 容错性最好：不会报错！
	 * 可以嵌套 Input复合的类型。
	 * */
	@MutationMapping
	public Boolean syncEqpFromLegacy复杂情况(@Arguments MyInputProjection in
	) {
		String type = in.getType();
		String arg = in.getArg();
		String pasw = in.getPasw();
		Integer	offset = in.getOffset();
		ComomnBaseInput commonBaseInput=in.getObj();
		UUID mid =commonBaseInput.getId();
		String mname= commonBaseInput.getName();
		return true;
	}
	/** 有一点优点： 客户端发送的参数一个都可以省略的，但写法也挺奇怪的；还是不好！
	 * */
	@MutationMapping
	public Boolean syncEqpFromLegacy77(@Argument  Map<String, Object>  args
	) {
		String type = (String) args.get("type");
		String pasw = (String) args.get("pasw");
		Integer	offset = (Integer) args.get("offset");
		return true;
	}
	/**最佳做法： 客户端发送的参数可省略String声明类型的，int声明参数不能省=会报错；
	 * 参数定义把int offset改成Integer offset后可省略不会报错。
	 * CommonBaseInput 最少要求 obj:{} 不然报错Source must not be null!。
	 * 最后把interface ComomnBaseInput改成class ComomnBaseInput在遇到obj没有输入时刻随意的：不会报错，
	 * obj参数：参数位置可随意的，Java定义类型ComomnBaseInput 和模型文件*.graphqls定义名字CommonBaseInput的没有对上但也不报错！。
	 *采用@ProjectedPayload interface CommonBaseInput 最少要求 obj:{} 不然错；
	 * */
	@MutationMapping
	public Boolean syncEqpFromLegacy(@Argument String type, @Argument String arg, @Argument String pasw, @Argument Integer offset,
										 @Argument ComomnBaseInput obj,
									 GraphQLContext ctx, DataFetchingEnvironment env
	) {
		if(null==obj) return false;
		UUID mid = obj.getId();
		String mname = obj.getName();
		return true;
	}
	/** 比较啰嗦： 客户端发送的参数offset不能省略，否则报错；
	 * */
	@MutationMapping
	public Boolean syncEqpFromLegacy78(@Argument("type") String type, @Argument("arg") String arg, @Argument("pasw") String pasw, @Argument("offset") int offset,
									 GraphQLContext ctx, DataFetchingEnvironment env
									 ) {
		String employeeId ="";// arg;
	//	Integer salary = offset;
//		JsliceMang ackjm=new JsliceMang();
//		ackjm.setOffs(222);
		return true;
	}
}


/** 输入参数的塑造：CommonBaseInput
* */
@ProjectedPayload
interface MyInputProjection {
	String getType();
	String getArg();
	String getPasw();
	Integer getOffset();

	ComomnBaseInput getObj();
}

/** 嵌套时没必要注解@ProjectedPayload
 * 但是用在接口函数上作为输入参数直接能够看见的第一层次接收的就必须要注解@ProjectedPayload。
 * */
@ProjectedPayload
interface CommonBaseInput {
	UUID getId();
	String getName();
}


/**
 * interface改成class在遇到obj没有输入时刻就不会报错
 * @Getter
 * @Setter
 */
@Value
class ComomnBaseInput {
	@NotNull
	UUID id;
	@NotNull
	//@Size(max=13)
	String name;
}

